import { BaseModel } from './BaseModel'
import { fileUploadService } from "server/utils/fileUpload";
import bcrypt from 'bcrypt'

export interface UserData {
  id?: number
  username: string
  email: string
  password?: string
  nickname?: string
  avatar?: number
  avatar_url?: string
  bio?: string
  role: 'admin' | 'user'
  status: 'active' | 'inactive' | 'banned'
  created_at?: string
  updated_at?: string
}

export interface SafeUserData extends Omit<UserData, 'password'> {}

export class User extends BaseModel {
  protected static tableName = 'users'

  // 创建用户（密码加密）
  static async createUser(data: Omit<UserData, 'id' | 'created_at' | 'updated_at'>): Promise<number> {
    // 检查用户名和邮箱是否已存在
    if (await this.isUsernameExists(data.username)) {
      throw new Error('用户名已存在')
    }
    
    if (await this.isEmailExists(data.email)) {
      throw new Error('邮箱已存在')
    }

    // 加密密码
    if (data.password) {
      data.password = await bcrypt.hash(data.password, 10)
    }

    return this.create(data)
  }

  // 验证用户登录
  static async validateLogin(usernameOrEmail: string, password: string): Promise<SafeUserData | null> {
    const sql = `
      SELECT * FROM users 
      WHERE (username = ? OR email = ?) AND status = 'active'
    `
    const result = await this.query<UserData[]>(sql, [usernameOrEmail, usernameOrEmail])
    const users = result[0] || []
    
    if (users.length === 0) {
      return null
    }

    const user = users[0]
    
    
    // 验证密码
    if (user?.password && await bcrypt.compare(password, user.password)) {
      // 返回安全的用户数据（不包含密码）
      const { password: _, ...safeUser } = user
      return safeUser
    }

    return null
  }

  // 根据ID获取安全用户数据
  static async getSafeUserById(id: number): Promise<SafeUserData | null> {
    const sql = `
      SELECT id, username, email, nickname, avatar, bio, role, status, created_at, updated_at
      FROM users 
      WHERE id = ?
    `
    const result = await this.query<SafeUserData[]>(sql, [id])
    const rows = result[0] || []
    const users = rows.length > 0 ? rows[0] ?? null : null
    if (users?.avatar) {
      users.avatar_url = await fileUploadService.generateFileUrlById(users.avatar)
    }
    return users
  }

  // 检查用户名是否存在
  static async isUsernameExists(username: string, excludeId?: number): Promise<boolean> {
    let sql = `SELECT COUNT(*) as count FROM users WHERE username = ?`
    const params: any[] = [username]
    
    if (excludeId) {
      sql += ` AND id != ?`
      params.push(excludeId)
    }
    
    const result = await this.query<{count: number}[]>(sql, params)
    return (result[0]?.[0] as {count: number})?.count > 0
  }

  // 检查邮箱是否存在
  static async isEmailExists(email: string, excludeId?: number): Promise<boolean> {
    let sql = `SELECT COUNT(*) as count FROM users WHERE email = ?`
    const params: any[] = [email]
    
    if (excludeId) {
      sql += ` AND id != ?`
      params.push(excludeId)
    }
    
    const result = await this.query<{count: number}[]>(sql, params)
    return (result[0]?.[0] as {count: number})?.count > 0
  }

  // 更新用户资料
  static async updateProfile(id: number, data: Partial<UserData>): Promise<boolean> {
    // 如果更新用户名，检查是否已存在
    if (data.username && await this.isUsernameExists(data.username, id)) {
      throw new Error('用户名已存在')
    }
    
    // 如果更新邮箱，检查是否已存在
    if (data.email && await this.isEmailExists(data.email, id)) {
      throw new Error('邮箱已存在')
    }

    // 如果更新密码，需要加密
    if (data.password) {
      data.password = await bcrypt.hash(data.password, 10)
    }

    return this.update(id, data)
  }

  // 实现具体的update方法
  static async update(id: number | string, data: any): Promise<boolean> {
    const fields: string[] = []
    const values: any[] = []

    Object.entries(data).forEach(([key, value]) => {
      if (value !== undefined) {
        fields.push(`${key} = ?`)
        values.push(value)
      }
    })

    if (fields.length === 0) return false

    fields.push("updated_at = CURRENT_TIMESTAMP")

    const sql = `UPDATE ${this.tableName} SET ${fields.join(", ")} WHERE id = ?`
    const result = await this.execute(sql, [...values, id])

    return result.affectedRows > 0
  }

  // 修改密码
  static async changePassword(id: number, oldPassword: string, newPassword: string): Promise<boolean> {
    // 获取用户当前密码
    const sql = `SELECT password FROM users WHERE id = ?`
    const result = await this.query<{password: string}[]>(sql, [id])
    const users = result[0] || []
    
    if (users.length === 0) {
      throw new Error('用户不存在')
    }

    const user = users[0]
    
    // 验证旧密码
    if (!user || !await bcrypt.compare(oldPassword, user.password)) {
      throw new Error('原密码错误')
    }

    // 更新新密码
    const hashedNewPassword = await bcrypt.hash(newPassword, 10)
    return this.update(id.toString(), { password: hashedNewPassword })
  }

  // 获取所有用户（管理员功能）
  static async getAllUsers(page: number = 1, pageSize: number = 10): Promise<{
    data: SafeUserData[]
    total: number
    page: number
    pageSize: number
    totalPages: number
  }> {
    // 确保 page 和 pageSize 是正整数
    const safePage = Math.max(1, Math.floor(Number(page)))
    const safePageSize = Math.max(1, Math.min(50, Math.floor(Number(pageSize))))
    const offset = (safePage - 1) * safePageSize

    // 查询总数
    const countSql = `SELECT COUNT(*) as total FROM users`
    const countResult = await this.query<{total: number}[]>(countSql)
    const total = (countResult[0]?.[0] as {total: number})?.total || 0

    // 使用字符串拼接的方式处理 LIMIT 和 OFFSET，避免预处理语句参数问题
    const dataSql = `
      SELECT id, username, email, nickname, avatar, bio, role, status, created_at, updated_at
      FROM users
      ORDER BY created_at DESC
      LIMIT ${safePageSize} OFFSET ${offset}
    `
    const result = await this.query<SafeUserData[]>(dataSql, [])
    const users = result[0] || []

    return {
      data: users,
      total,
      page: safePage,
      pageSize: safePageSize,
      totalPages: Math.ceil(total / safePageSize)
    }
  }
}